--Universidade Federal de Campina Grande
--Centro de Enegenharia Elétrica e Informática
--Unidade Acadêmica de Sistemas e Computação
--Disciplina: Paradigmas de Linguagens de Programação
--Professor: Franklin Ramalho
--Equipe: Arthur Ribeiro
--        Felipe Vieira
--        Jeysibel Dantas
--        Paulo Victor
--Euphoric Checkers
--
include utils.ex
include board.ex


sequence takes = {}

export procedure verifyEnemyAround(atom lineStart, atom columnStart, atom player, sequence partialCheck, atom lastLineChecked, atom lastColumnChecked)
/*
{ {1},{3,6,4,5}
  {2}, {3,6,4,5}, {4,5,6,7}
}   
*/


 


--if enemy is black pieces
if equal(player,WHITE) then 
  --from board.ex
  --return a sequence in this order LF,RF,LB,RB
  sequence adjacents = findWhitePieceAdjacents(lineStart,columnStart)
  atom lineLF = adjacents[1][1]
  atom columnLF = adjacents[1][2]
  atom lineRF = adjacents[2][1]
  atom columnRF = adjacents[2][2]
  atom lineLB = adjacents[3][1]
  atom columnLB = adjacents[3][2]
  atom lineRB = adjacents[4][1]
  atom columnRB = adjacents[4][2]


  --left forward
  if not equal(columnLF,0) and not equal(columnLF,1) and not equal(lineLF,0) and not equal(lineLF,1)then
      if not (equal(lineLF,lastLineChecked) and equal(columnLF,lastColumnChecked)) then
        if equal(board[lineLF][columnLF],BLACK) and equal(board[lineLF-1][columnLF-1],EMPTY)  then
          if equal(partialCheck,{}) then
            sequence partial = {{1}, {lineStart,columnStart,lineLF,columnLF,lineLF-1,columnLF-1}}
                takes = append(takes,partial)

            verifyEnemyAround(lineLF-1,columnLF-1,WHITE,partial,lineLF,columnLF)
          else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineLF,columnLF,lineLF-1,columnLF-1})
            takes = append(takes,partial)
            verifyEnemyAround(lineLF-1,columnLF-1,WHITE,partial,lineLF,columnLF)
          end if
        end if
      end if
   end if
    --right forward 
   if not equal(columnRF,9) and not equal(columnRF,8) and not equal(lineRF,0) and not equal(lineRF,1) then 
      if not (equal(lineRF,lastLineChecked) and equal(columnRF,lastColumnChecked)) then
          if equal(board[lineRF][columnRF],BLACK) and equal(board[lineRF-1][columnRF+1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineRF,columnRF,lineRF-1,columnRF+1}}
                takes = append(takes,partial)

                verifyEnemyAround(lineRF-1,columnRF+1,WHITE,partial,lineRF,columnRF)
              else 
              sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineRF,columnRF,lineRF-1,columnRF+1})
                takes = append(takes,partial)
                verifyEnemyAround(lineRF-1,columnRF+1,WHITE,partial,lineRF,columnRF)
              end if
          end if
      end if
    end if
    --left backward
    if not equal(columnLB,0) and not equal(columnLB,1) and not equal(lineLB,9) and not equal(lineLB,8) then 
      if not (equal(lineLB,lastLineChecked) and equal(columnLB,lastColumnChecked)) then
          if equal(board[lineLB][columnLB],BLACK) and equal(board[lineLB+1][columnLB-1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineLB,columnLB,lineLB+1,columnLB-1}}
                takes = append(takes,partial)
                verifyEnemyAround(lineLB+1,columnLB-1,WHITE,partial,lineLB,columnLB)
              else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineLB,columnLB,lineLB+1,columnLB-1})
                takes = append(takes,partial)
                verifyEnemyAround(lineLB+1,columnLB-1,WHITE,partial,lineLB,columnLB)
              end if
          end if
      end if
     end if
--right backward
    if not equal(columnRB,9) and not equal(columnRB,8) and not equal(lineRB,9) and not equal(lineRB,8) then
        if not (equal(lineRB,lastLineChecked) and equal(columnRB,lastColumnChecked)) then
          if equal(board[lineRB][columnRB],BLACK) and equal(board[lineRB+1][columnRB+1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineRB,columnRB,lineRB+1,columnRB+1}}
                takes = append(takes,partial)
                verifyEnemyAround(lineRB+1,columnRB+1,WHITE,partial,lineRB,columnRB)
              else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineRB,columnRB,lineRB+1,columnRB+1})
                takes = append(takes,partial)
                verifyEnemyAround(lineRB+1,columnRB+1,WHITE,partial,lineRB,columnRB)
              end if
          end if
        end if
     end if
-- 
--        takes = append(takes,partialCheck)
--        puts(1,"Terminou Recursão: Takes : \n")
--        ?takes
--     end if

else 

  --from board.ex
  --return a sequence in this order LF,RF,LB,RB
  sequence adjacents = findBlackPieceAdjacents(lineStart,columnStart)

  atom lineLF = adjacents[1][1]
  atom columnLF = adjacents[1][2]
  atom lineRF = adjacents[2][1]
  atom columnRF = adjacents[2][2]
  atom lineLB = adjacents[3][1]
  atom columnLB = adjacents[3][2]
  atom lineRB = adjacents[4][1]
  atom columnRB = adjacents[4][2]


 --left forward
  if not equal(columnLF,8) and not equal(columnLF,9) and not equal(lineLF,8) and not equal(lineLF,9)then
      if not (equal(lineLF,lastLineChecked) and equal(columnLF,lastColumnChecked)) then
        if equal(board[lineLF][columnLF],WHITE) and equal(board[lineLF+1][columnLF+1],EMPTY)  then
          if equal(partialCheck,{}) then
            sequence partial = {{1}, {lineStart,columnStart,lineLF,columnLF,lineLF+1,columnLF+1}}
                takes = append(takes,partial)

            verifyEnemyAround(lineLF+1,columnLF+1,BLACK,partial,lineLF,columnLF)
          else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineLF,columnLF,lineLF+1,columnLF+1})
            takes = append(takes,partial)
            verifyEnemyAround(lineLF+1,columnLF+1,BLACK,partial,lineLF,columnLF)
          end if
        end if
      end if
   end if
    --right forward 
   if not equal(columnRF,0) and not equal(columnRF,1) and not equal(lineRF,8) and not equal(lineRF,9) then 
      if not (equal(lineRF,lastLineChecked) and equal(columnRF,lastColumnChecked)) then
          if equal(board[lineRF][columnRF],WHITE) and equal(board[lineRF+1][columnRF-1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineRF,columnRF,lineRF+1,columnRF-1}}
                takes = append(takes,partial)

                verifyEnemyAround(lineRF+1,columnRF-1,BLACK,partial,lineRF,columnRF)
              else 
          sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineRF,columnRF,lineRF+1,columnRF-1})
                takes = append(takes,partial)
                verifyEnemyAround(lineRF+1,columnRF-1,BLACK,partial,lineRF,columnRF)
              end if
          end if
      end if
    end if
    --left backward
    if not equal(columnLB,8) and not equal(columnLB,9) and not equal(lineLB,0) and not equal(lineLB,1) then 
      if not (equal(lineLB,lastLineChecked) and equal(columnLB,lastColumnChecked)) then
          if equal(board[lineLB][columnLB],WHITE) and equal(board[lineLB-1][columnLB+1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineLB,columnLB,lineLB-1,columnLB+1}}
                takes = append(takes,partial)
                verifyEnemyAround(lineLB-1,columnLB+1,BLACK,partial,lineLB,columnLB)
              else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineLB,columnLB,lineLB-1,columnLB+1})
                takes = append(takes,partial)
                verifyEnemyAround(lineLB-1,columnLB+1,BLACK,partial,lineLB,columnLB)
              end if
          end if
      end if
     end if
--right backward
    if not equal(columnRB,0) and not equal(columnRB,1) and not equal(lineRB,0) and not equal(lineRB,1) then
        if not (equal(lineRB,lastLineChecked) and equal(columnRB,lastColumnChecked)) then
          if equal(board[lineRB][columnRB],WHITE) and equal(board[lineRB-1][columnRB-1],EMPTY)  then
              if equal(partialCheck,{}) then
                sequence partial = {{1}, {lineStart,columnStart,lineRB,columnRB,lineRB-1,columnRB-1}}
                takes = append(takes,partial)
                verifyEnemyAround(lineRB-1,columnRB-1,BLACK,partial,lineRB,columnRB)
              else 
            sequence partial = partialCheck
            partial[1][1] = partial[1][1] + 1
            partial =  append(partial, {lineStart,columnStart,lineRB,columnRB,lineRB-1,columnRB-1})
                takes = append(takes,partial)
                verifyEnemyAround(lineRB-1,columnRB-1,BLACK,partial,lineRB,columnRB)
              end if
          end if
        end if
     end if
--     else 
--        takes = append(takes,partialCheck)
--        puts(1,"Terminou Recursão: Takes : \n")
--        ?takes
--     end if
end if


end procedure

export function performWhiteTake(sequence board, sequence takeChoosen)

integer catcherLine = takeChoosen[1]
integer catcherColumn = takeChoosen[2]
integer catchableLine = takeChoosen[3]
integer catchableColumn = takeChoosen[4]

    -- Forward take
    if catcherLine<catchableLine then

      -- Right take
      if catcherColumn<catchableColumn then
        -- Verify possibility
          if isValidPosition(catchableLine+1,catcherColumn+1) then
            if board[catchableLine+1][catchableColumn+1]=0 then 

            board[catchableLine+1][catchableColumn+1]=1
            board[catcherLine][catcherColumn]=0
            board[catchableLine][catchableColumn]=0
            

            end if
          end if
          
      
      -- Left Take
      else 

        if isValidPosition(catchableLine+1,catcherColumn-1) then 
          if board[catchableLine+1][catchableColumn-1]=0 then 
         
            board[catchableLine+1][catchableColumn-1]=1
            board[catcherLine][catcherColumn]=0
            board[catchableLine][catchableColumn]=0
          end if      
        end if

    end if

      -- Backward take
    
    if catcherLine>catchableLine then
      -- Right Take
    
      if catcherColumn<catchableColumn then
        -- Verify possibility
        if isValidPosition(catchableLine-1,catcherColumn+1) then
          if board[catchableLine-1][catchableColumn+1]=0 then 
            
            board[catchableLine-1][catchableColumn+1]=1
            board[catcherLine][catcherColumn]="   -    "
            board[catchableLine][catchableColumn]="   -    "
          end if
        end if
      
      else 
  
        if isValidPosition(catchableLine-1,catcherColumn-1) then 
          if board[catchableLine-1][catchableColumn-1]=0 then 
            
            board[catchableLine-1][catchableColumn-1]=1
            board[catcherLine][catcherColumn]="   -    "
            board[catchableLine][catchableColumn]="   -    "
          end if
        end if
    end if
end if
end if
 return 1 
end function


export function performBlackTake(sequence board, sequence takeChoosen)
integer catcherLine = takeChoosen[1]
integer catcherCell = takeChoosen[2]
integer catchableLine = takeChoosen[3]
integer catchableCell = takeChoosen[4]
    -- Forward take
    if catcherLine<catchableLine then
      -- Right take
      if catcherCell<catchableCell then
        -- Verify possibility
          if isValidPosition(catchableLine+1,catcherCell+1) then
            if board[catchableLine+1][catchableCell+1]=0 then 

            board[catchableLine+1][catchableCell+1]=2
            board[catcherLine][catcherCell]=0
            board[catchableLine][catchableCell]=0
            

            end if
          end if
      end if
      
      -- Left Take
      if catcherCell>catchableCell then

        if isValidPosition(catchableLine+1,catcherCell-1) then 
          if board[catchableLine+1][catchableCell-1]=0 then 
         
            board[catchableLine+1][catchableCell-1]=2
            board[catcherLine][catcherCell]=0
            board[catchableLine][catchableCell]=0
          end if      
        end if

    end if
  end if

      -- Backward take
    
    if catcherLine>catchableLine then

      -- Right Take
        
     
    
      if catcherCell<catchableCell then
        -- Verify possibility
        if isValidPosition(catchableLine-1,catcherCell+1) then
          if board[catchableLine-1][catchableCell+1]=0 then 
            
            board[catchableLine-1][catchableCell+1]=2
            board[catcherLine][catcherCell]=0
            board[catchableLine][catchableCell]=0
          end if
        end if
      
      end if

      if catcherCell>catchableCell then
  
        if isValidPosition(catchableLine-1,catcherCell-1) then 
          if board[catchableLine-1][catchableCell-1]=0 then 
            
            board[catchableLine-1][catchableCell-1]=2
            board[catcherLine][catcherCell]=0
            board[catchableLine][catchableCell]=0
          end if
        end if
      end if
    end if
return 1
end function


export function verifyPositionWhenWhiteIsTaking(atom catcherLine, atom catcherCell, atom catchableLine, atom catchableCell)
    if catcherLine<catchableLine then
        if catchableCell>catcherCell then return {catchableLine+1,catchableCell+1} end if
        if catchableCell<catcherCell then return {catchableLine+1,catchableCell-1} end if
    else
        if catchableCell>catcherCell then return {catchableLine-1,catchableCell+1} end if
        if catchableCell<catcherCell then return {catchableLine-1,catchableCell-1} end if
    end if
end function
    

export function verifyWhitePossibleTakes()
      sequence setOfPossibleTakes = {}    
     takes = {}
      for i=1 to length(board) do
        for j=1 to length(board[i]) do
          if board[i][j]=WHITE then
              verifyEnemyAround(i,j,WHITE,{},i,j)
          end if
        end for
      end for
-- puts(1,"Tomadas Possíveis:\n")
--       ?takes



if(length(takes) >0) then      
  sequence takes2 = orderTakes(takes)

--   puts(1,"Tomadas Possíveis Ordenadas:\n")
--      ?takes2
  takes2 = excludeMinorTakes(takes2)  

  --puts(1,"Tomadas Possíveis Filtradas:\n")
        --?takes2    
return takes
end if

return takes

end function


procedure performSingleTake(atom startLine,atom startColumn,atom enemyLine,atom enemyColumn, atom stopLine,atom stopColumn)

atom color = board[startLine][startColumn]
board[enemyLine][enemyColumn] = EMPTY
board[startLine][startColumn] = EMPTY
board[stopLine][stopColumn] = color
end procedure 


export procedure performTakes(sequence choosedTake)

for i=2 to length(choosedTake) do
    performSingleTake(choosedTake[i][1],choosedTake[i][2],choosedTake[i][3],choosedTake[i][4],choosedTake[i][5],choosedTake[i][6])
end for

end procedure



export function verifyBlackPossibleTakes()
      sequence setOfPossibleTakes = {}  
     takes = {}
      for i=1 to length(board) do
        for j=1 to length(board[i]) do
          if board[i][j]=BLACK then
           verifyEnemyAround(i,j,BLACK,{},i,j)
          end if
        end for
      end for


-- puts(1,"Tomadas Possíveis:\n")
--       ?takes

if(length(takes) >0) then      
  sequence takes2 = orderTakes(takes)

  --puts(1,"Tomadas Possíveis Ordenadas:\n")
--?takes2
  takes2 = excludeMinorTakes(takes2)  

  --puts(1,"Tomadas Possíveis Filtradas:\n")
        --?takes2    
  return takes2
end if

return takes
end function
      

function excludeMinorTakes(sequence orderedTakes)
atom cutPoint = orderedTakes[1][1][1]

sequence filteredTakes = {}

for i=1 to length(orderedTakes) do
      if equal(orderedTakes[i][1][1],cutPoint) then
          filteredTakes = append(filteredTakes,orderedTakes[i])
      end if
  end for

return filteredTakes

end function

export function verifyIfCanTakeEnemy(atom startLine,atom  startColumn, atom stopLine, atom stopColumn, sequence availableTake)

    atom numSimpleTakes = availableTake[1][1]
    atom takeStartLine = availableTake[2][1]
    atom takeStartColumn = availableTake[2][2]
    atom takeStopLine = availableTake[numSimpleTakes+1][5]
    atom takeStopColumn = availableTake[numSimpleTakes+1][6]
    if equal(startLine,takeStartLine) and equal(startColumn,takeStartColumn) and equal(stopLine,takeStopLine) and equal(stopColumn,takeStopColumn) then
      return TRUE
    end if


return FALSE

end function


function orderTakes(sequence takes)
sequence takesOrdered = {}
  for i=1 to length(takes) do
      if equal(takes[i][1][1],7) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],6) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],5) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],4) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],3) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],2) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
  for i=1 to length(takes) do
      if equal(takes[i][1][1],1) then
          takesOrdered = append(takesOrdered,takes[i])
      end if
  end for
 
return takesOrdered
end function
